// ==UserScript==
// @name         采集表审核助手
// @namespace    http://xg.mediportal.com.cn/
// @version      0.5
// @description  数字化营销临床调研采集表审核助手
// @author       Waylon Wang
// @icon         https://default-hn.file.hubmedi.com.cn/user/default_man.jpg
// @match        *://*/ysf-case-pc/*
// @license      MIT
// @grant        none
// ==/UserScript==


(function () {
    'use strict';


    let css = `
  .tag {
    margin: 2px;
    padding: 4px;
    background-color: #f0f0f0;
    border-radius: 4px;
    cursor: pointer;
  }

  .selected-tag {
    background-color: #007bff;
    color: white;
  }

  .delete-icon {
    width: 20px;
    height: 20px;
    border-radius: 10px;
    margin-left: 10px;
    cursor: pointer;
    justify-content: center;
    align-items: center;
    display: inline-flex;
    transform: scale(0.8)
    filter: brightness(100%);
    transition: filter 0.3s ease;
  }

  .delete-icon:hover {
    filter: brightness(90%);
  }

  .tag .delete-icon{
    background-color: #fcfcfc;
    color: #999999;
  }

  .selected-tag .delete-icon{
    background-color: #509ef1;
    color: #ffffff;
  }

  .error-border{
    border-color: red;
  }

  .modal-container {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background-color: rgba(0, 0, 0, 0.5);
    z-index: 9999;
  }

  .modal-content {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    background-color: white;
    padding: 20px;
    border-radius: 5px;
    box-shadow: 0 0 10px rgba(0, 0, 0, 0.3);
    max-width: 90%;
    display: flex;
    flex-direction: column;
  }

  .tages-container {
    display: flex;
    flex-wrap: wrap;
    margin-bottom: 10px;
    width: 500px;
  }

  .name-input {
    width: 500px;
    height: 30px;
    margin-bottom: 10px;
  }

  .project-input {
    width: 500px;
    height: 30px;
    resize: none;
    margin-bottom: 10px;    
  }

  .limit-input {
    width: 500px;
    height: 300px;
    resize: none;
    margin-bottom: 10px;
    overflow-y: auto;
  }

  .rule-input {
    width: 500px;
    height: 100px;
    resize: none;
    overflow-y: auto;
  }

  .button-container {
    display: flex;
    justify-content: space-between;
  }

  .right-button-container {
    display: flex;
    justify-content: space-between;
  }

  .confirm-button {
    margin-top: 10px;
    margin-left: auto; 
  }

  .cancel-button {
    margin-top: 10px;
    margin-right: 10px; 
  }

  .save-button {
    margin-top: 10px;
  }

  .config-button {
    position: fixed; 
    top: 80px; 
    left: calc(50% - 205px);
    transform: translateX(-50%);
    z-index: 9999; 
    width: 50px; 
    height: 50px; 
    border-radius: 25px;
    cursor: pointer;
    filter: brightness(100%);
    transition: filter 0.3s ease;
  }

  .config-button:hover {
    filter: brightness(90%);
  }

  .hint-panel {
    position: fixed;
    top: 75px; 
    left: 50%; 
    transform: translateX(-50%); 
    z-index: 9998;
    width: 400px;
    height: 60px;
    background-color: white;
    box-shadow: 0 0 10px rgba(0, 0, 0, 0.3);
    border-radius: 30px;
    padding-left: 70px;
    display: flex;
    align-items: center;
    justify-content: left;
    color: #cccccc;
  }

  .ai-status {
    position: fixed;
    top: 88px;
    left: calc(50% + 203px);
    transform: translateX(-50%);
    z-index: 9999;
    width: 30px;
    height: 30px;
    border-radius: 20px;
    border: 2px solid white;
    font-size: 16px;
    background-color: #cccccc;
    color: white;
    justify-content: center;
    align-items: center;
    display: inline-flex;
  }

  .allow {
    background-color: #51e297;
    color: white;
  }

  .deny {
    background-color: #e25180;
    color: white;
  }

  .unknow {
    background-color: white;
    color: #cccccc;   
  }

  .ai-allow {
    background-color: #51e297;
  }

  .ai-deny {
    background-color: #e25180;
  }

  .ai-unknow {
    background-color: #cccccc; 
  }

  .ai-tips {
    position: fixed;
    top: 130px;
    left: calc(50% + 203px);
    transform: translateX(-50%);
    z-index: 9999;
    width: fit-content;
    min-width: 100px;
    border-radius: 5px;
    font-size: 14px;
    background-color: white;
    color: #666666;
    display: none;
    align-items: center;
    justify-content: center;
    box-shadow: 0 0 10px rgba(0, 0, 0, 0.3);   
    padding: 5px;
    cursor: default;
}

 .ai-tips pre{    
    word-wrap: break-word;    
    white-space: break-spaces;
    padding-left: 12px;
    padding-right: 12px;
  }

      `;

    // 注入CSS
    (css => {
        let styleElement = document.createElement('style');
        styleElement.type = 'text/css';
        styleElement.textContent = css;
        document.head.appendChild(styleElement);
    })(css);

    // 定义XHR Interceptor
    function XHRInterceptor() {
        // 保存原始的XMLHttpRequest对象
        let originalXHR = window.XMLHttpRequest;

        // 创建代理XHR对象
        function ProxyXHR() {
            let xhr = new originalXHR();

            // 拦截并监控XHR请求
            xhr.addEventListener('load', function () {
                console.log('Load XHR:', xhr.responseURL);
                let targetUrl = `${window.location.hostname}/disease-marketing/case/check/v2/answerDetail`;
                if (xhr.responseURL.includes(targetUrl)) {
                    console.log('拦截URL:', xhr.responseURL);
                    currentCollection = analyseXHR(xhr);
                    doAction(currentCollection);
                }
            });

            return xhr;
        }

        // 替换原始的XMLHttpRequest对象为代理XHR对象
        window.XMLHttpRequest = ProxyXHR;
    }

    // 分析响应数据
    function analyseXHR(xhr) {
        let data = JSON.parse(xhr.responseText).data;
        let doctor = {
            'name': data.name,
            'tel': data.tel,
            'caseTotalCount': Number(data.caseTotalCount),
            'passCaseCount': Number(data.passCaseCount),
            'checkedNum': Number(data.checkedNum),
            'patientTotalCount': Number(data.patientTotalCount),
            'passPatientCount': Number(data.passPatientCount),
            'remark': data.remark
        };
        let collection = { ...data };
        collection.doctor = doctor;
        data.answerInfo.forEach(function (answer) {
            if (answer.type === 'PATIENT') {
                collection.patient = answer;
            } else {
                collection.answer = answer;
            }
        });
        return collection;
    }

    // 显示提示框
    function showHintBox() {
        let configButton = document.createElement('img');
        let hintPanel = document.createElement('div');
        let aiStatus = document.createElement('div');
        let aiTips = document.createElement('div');

        configButton.src = 'https://default-hn.file.hubmedi.com.cn/user/default_man.jpg';
        configButton.classList.add("config-button");

        hintPanel.textContent = '';
        hintPanel.id = 'checkHint';
        hintPanel.classList.add("hint-panel");

        aiStatus.textContent = 'AI';
        aiStatus.id = 'aiStatus';
        aiStatus.classList.add("ai-status");

        aiTips.textContent = '';
        aiTips.id = 'aiTips';
        aiTips.classList.add("ai-tips");

        // 监听点击事件
        configButton.addEventListener('click', function () {
            showConfigDialog(localStorage.getItem('schemaName') || '').then(function (input) {
                loadConfig();
                if (currentCollection) {
                    doAction(currentCollection);
                }
            });
        });

        aiStatus.addEventListener("mouseover", () => { aiTips.style.display = "flex"; });
        aiStatus.addEventListener("mouseout", () => { setTimeout(() => { aiTips.style.display = "none"; }, 1000); });

        document.body.appendChild(hintPanel);
        document.body.appendChild(configButton);
        document.body.appendChild(aiStatus);
        document.body.appendChild(aiTips);
    }

    // 显示配置对话框
    function showConfigDialog() {
        return new Promise(function (resolve, reject) {
            let currentSchemaName = '';

            // 获取所有已保存的名称
            function getAllSavedNames() {
                let savedNames = [];
                for (let i = 0; i < localStorage.length; i++) {
                    let key = localStorage.key(i);
                    if (key.startsWith("schema_")) {
                        let name = key.replace("schema_", "");
                        savedNames.push(name);
                    }
                }
                savedNames.sort();
                return savedNames;
            }

            // 创建已保存名称标签
            function createSavedNameTag(name) {
                let tag = document.createElement("span");
                tag.textContent = name;
                tag.classList.add("tag");
                tag.classList.add("el-button");

                // 高亮当前选择的标签
                if (currentSchemaName === name) {
                    tag.classList.add("selected-tag");
                }

                // 添加删除图标
                let deleteIcon = document.createElement("span");
                deleteIcon.textContent = "✕";
                deleteIcon.classList.add("delete-icon");
                deleteIcon.addEventListener("click", function (event) {
                    event.stopPropagation();
                    deleteSavedData(name);
                    tag.parentNode.removeChild(tag);
                });
                tag.appendChild(deleteIcon);

                tag.addEventListener("click", function () {
                    loadSavedData(name);
                    updateSelectedTag(name);
                });

                return tag;
            }

            // 更新已保存名称标签
            function updateSavedNamesTags() {
                let tagsContainer = document.querySelector("#tagsContainer");
                tagsContainer.innerHTML = ""; // Clear the container first
                let savedNames = getAllSavedNames();
                savedNames.forEach(function (name) {
                    let tag = createSavedNameTag(name);
                    tagsContainer.appendChild(tag);
                });
            }

            // 加载已保存数据到文本框
            function loadSavedData(name) {
                let key = "schema_" + name;
                if (localStorage.getItem(key)) {
                    let savedData = JSON.parse(localStorage.getItem(key));
                    nameInput.value = name;
                    projectInput.value = savedData[0];
                    limitInput.value = savedData[1];
                    ruleInput.value = savedData[2];
                }
            }

            // 删除方案及相关数据
            function deleteSavedData(name) {
                let key = "schema_" + name;
                localStorage.removeItem(key);

                // 删除当前选择的标签
                if (currentSchemaName === name) {
                    nameInput.value = "";
                    projectInput.value = "";
                    limitInput.value = "";
                    ruleInput.value = "";
                    localStorage.removeItem("schemaName");
                }
                updateSavedNamesTags();
            }

            // 更新已保存名称标签的选中状态
            function updateSelectedTag(name) {
                let tagsContainer = document.querySelector("#tagsContainer");
                let tags = tagsContainer.querySelectorAll("span.tag");
                tags.forEach(function (tag) {
                    tag.classList.remove("selected-tag");
                    tag.classList.remove("el-button--primary");
                    tag.classList.add("el-button--default");
                    if (tag.textContent === name + '✕') {
                        currentSchemaName = name;
                        tag.classList.add("selected-tag");
                        tag.classList.add("el-button--primary");
                        tag.classList.remove("el-button--default");
                    }
                });
            }

            // 保存方案
            function saveSchema() {
                let userInput1 = nameInput.value.trim();
                let userInput2 = projectInput.value;
                let userInput3 = limitInput.value;
                let userInput4 = ruleInput.value;

                if (!userInput1) {
                    nameInput.classList.add('error-border');
                    return false;
                } else {
                    nameInput.classList.remove('error-border');
                }

                // 保存输入的内容到本地存储
                let key = "schema_" + userInput1;
                let data = [userInput2, userInput3, userInput4];
                currentSchemaName = userInput1;
                localStorage.setItem(key, JSON.stringify(data));
                // 更新已保存名称标签
                updateSavedNamesTags();
                return true;
            }

            // 创建模态框容器
            let modalContainer = document.createElement('div');
            // 创建模态框内容
            let modalContent = document.createElement('div');
            // 创建标签容器
            let tagsContainer = document.createElement("div");
            // 创建文本输入框1，用于填写名称
            let nameInput = document.createElement('input');
            // 创建文本输入框2，用于输入项目ID
            let projectInput = document.createElement('input');
            // 创建文本输入框3，用于医生采集表允许审核的数量上限
            let limitInput = document.createElement('textarea');
            // 创建文本输入框4，用于特殊匹配规则
            let ruleInput = document.createElement('textarea');
            // 创建按钮容器
            let buttonContainer = document.createElement('div');
            // 创建右侧按钮容器
            let rightButtonContainer = document.createElement('div');
            // 创建确认按钮
            let confirmButton = document.createElement('button');
            // 创建取消按钮
            let cancelButton = document.createElement('button');
            // 创建保存按钮
            let saveButton = document.createElement('button');

            modalContainer.classList.add("modal-container");
            modalContent.classList.add("modal-content");

            tagsContainer.id = "tagsContainer";
            tagsContainer.classList.add("tages-container");

            nameInput.type = 'text';
            nameInput.classList.add("name-input");
            nameInput.classList.add("el-textarea__inner");
            nameInput.placeholder = '输入方案名称';

            projectInput.classList.add("project-input");
            projectInput.classList.add("el-textarea__inner");
            projectInput.placeholder = '输入项目ID';

            limitInput.classList.add("limit-input");
            limitInput.classList.add("el-textarea__inner");
            limitInput.placeholder = '输入医生采集表允许审核的数量上限，每行一个医生，以英文逗号为分隔符，姓名和手机号必须填写一项\n\n格式为：姓名,手机号,数量\n\n样例：\n刘卫东,13312345678,16\n刘卫东,,16\n,13312345678,16';

            ruleInput.classList.add("rule-input");
            ruleInput.classList.add("el-textarea__inner");
            ruleInput.placeholder = '输入特殊匹配规则，每行一个JSON，JSON内容为采集表对象属性及匹配其值的正则表达式';

            buttonContainer.classList.add("button-container");

            rightButtonContainer.classList.add("right-button-container");

            confirmButton.classList.add("confirm-button");
            confirmButton.classList.add("el-button");
            confirmButton.classList.add("btn-size");
            confirmButton.classList.add("el-button--primary");

            confirmButton.textContent = '确定';

            cancelButton.textContent = '取消';
            cancelButton.classList.add("cancel-button");
            cancelButton.classList.add("el-button");
            cancelButton.classList.add("btn-size");
            cancelButton.classList.add("el-button--default");

            saveButton.textContent = '保存';
            saveButton.classList.add("save-button");
            saveButton.classList.add("el-button");
            saveButton.classList.add("btn-size");
            saveButton.classList.add("el-button--default");

            // 获取所有已保存的名称并创建标签显示
            let savedNames = getAllSavedNames();
            savedNames.forEach(function (name) {
                let tag = createSavedNameTag(name);
                tagsContainer.appendChild(tag);
            });

            // 组装布局
            rightButtonContainer.appendChild(cancelButton);
            rightButtonContainer.appendChild(confirmButton);
            buttonContainer.appendChild(saveButton);
            buttonContainer.appendChild(rightButtonContainer);

            modalContent.appendChild(tagsContainer);
            modalContent.appendChild(nameInput);
            modalContent.appendChild(projectInput);
            modalContent.appendChild(limitInput);
            modalContent.appendChild(ruleInput);
            modalContent.appendChild(buttonContainer);

            modalContainer.appendChild(modalContent);

            document.body.appendChild(modalContainer);

            // 确认按钮点击事件
            confirmButton.addEventListener('click', function () {
                // 保存数据
                if (saveSchema()) {
                    // 保存输入的内容到本地存储
                    localStorage.setItem('schemaName', currentSchemaName);
                    // 移除模态框
                    document.body.removeChild(modalContainer);
                    // 返回用户输入的内容数组
                    resolve(currentSchemaName);
                }
            });

            // 取消按钮点击事件
            cancelButton.addEventListener('click', function () {
                // 移除模态框
                document.body.removeChild(modalContainer);
                // 返回 null 表示用户取消输入
                resolve(null);
            });

            // 保存按钮点击事件
            saveButton.addEventListener('click', function () {
                // 保存数据
                saveSchema();
            });

            // 加载当前使用的方案
            currentSchemaName = localStorage.getItem('schemaName');
            if (currentSchemaName) {
                let key = "schema_" + currentSchemaName;

                // 检查本地存储中是否有之前保存的内容
                if (localStorage.getItem(key)) {
                    let savedData = JSON.parse(localStorage.getItem(key));
                    nameInput.value = currentSchemaName;
                    projectInput.value = savedData[0];
                    limitInput.value = savedData[1];
                    ruleInput.value = savedData[2];
                }
            }
            updateSelectedTag(currentSchemaName);
        });
    }

    // 执行活动
    function doAction(collection) {
        // AI识别
        interceptAI(collection);
        if (collection.projectId == projectId) {
            // 特殊规则拦截
            if (interceptSpecial(collection)) return;
            // 上限规则拦截
            if (interceptLimit(collection)) return;
        } else {
            unknow('项目未配置审核规则');
        }
    }

    // AI识别拦截
    function interceptAI(collection) {
        const xhr = new XMLHttpRequest();
        let url = `${window.location.protocol}//${window.location.hostname}/disease-marketing/case/ocr/openai/parse?id=${collection.id}`;

        xhr.open('GET', url, true);
        xhr.setRequestHeader('Content-Type', 'application/json;charset=UTF-8');
        xhr.setRequestHeader('access-token', token);

        xhr.onreadystatechange = function () {
            if (xhr.readyState === 4) {
                if (xhr.status === 200) {
                    const responseData = JSON.parse(xhr.responseText);
                    try {
                        const resultData = JSON.parse(responseData.data.content);
                        const key = 'state';
                        if (key in resultData) {
                            let result = resultData[key];
                            if (result === '审核通过') {
                                setAiTips(resultData);
                                aiAllow();
                                return false;
                            } else {
                                setAiTips(resultData);
                                aiDeny();
                                return true;
                            }
                        } else {
                            setAiTips(resultData);
                            aiUnknow();
                            return false;
                        }
                    } catch (e) {
                        setAiTips({ '识别结果': responseData.data.content });
                        aiUnknow();
                        return false;
                    }
                } else {
                    console.error('Error:', xhr.status);
                    setAiTips({ '识别结果': 'AI执行错误' });
                    aiUnknow();
                    return false;
                }
            }
        };

        xhr.send();

        function setAiTips(content) {
            let dom = document.querySelector('#aiTips');
            try {
                dom.innerHTML = `<pre>${JSON.stringify(content, null, 2)}<pre>`;
            } catch (e) {
                dom.textContent = content;
            }
        }

    }

    // 上限规则拦截
    function interceptLimit(collection) {
        let doctor = collection.doctor;
        let key = '';
        let key1 = doctor.name + '|' + doctor.tel;
        let key2 = doctor.name + '|';
        let key3 = '|' + doctor.tel;

        if (key1 in limitRules) {
            key = key1;
        } else if (key2 in limitRules) {
            key = key2;
        } else if (key3 in limitRules) {
            key = key3;
        } else {
            key = '-1';
        }

        let acceptNum = limitRules[key];
        if (acceptNum != null && acceptNum !== undefined) {
            if (doctor.passCaseCount < acceptNum) {
                allow('「' + doctor.name + '」的采集表未达到允许审核的上限(' + acceptNum + ')');
                return false;
            } else {
                deny('「' + doctor.name + '」的采集表已达到允许审核的上限(' + acceptNum + ')', true);
                return true;
            }
        } else {
            unknow('「' + doctor.name + '」未配置采集表允许审核的上限');
            return false;
        }
    }

    // 特殊规则拦截
    function interceptSpecial(collection) {
        // 假设你有以下文本
        for (let rule of specialRules) {
            let texts = [];
            let regexs = [];

            // 构建正则表达式
            for (let key in rule) {
                if (rule.hasOwnProperty(key)) {
                    let text = getPropertyByString(collection, key) || '';
                    texts.push(text);
                    regexs.push(new RegExp(rule[key]));
                }
            }

            let isAllMatched = true;
            for (let i = 0; i < texts.length; i++) {
                let isMatched = regexs[i].test(texts[i]);
                isAllMatched = isAllMatched && isMatched;
            }

            if (isAllMatched) {
                deny('「' + collection.doctor.name + '」命中了特殊匹配规则', false);
                return true;
            } else {
                return false;
            }
        }
    }

    // 允许处理
    function allow(hint) {
        let dom = document.querySelector('#checkHint');
        let button = document.querySelector('.btn-area .el-button--primary');
        dom.classList.add('allow');
        dom.classList.remove('deny');
        dom.classList.remove('unknow');
        dom.textContent = hint;
        button.style.display = '';
    }

    // 禁止处理
    function deny(hint, disable) {
        let dom = document.querySelector('#checkHint');
        let button = document.querySelector('.btn-area .el-button--primary');
        dom.classList.remove('allow');
        dom.classList.add('deny');
        dom.classList.remove('unknow');
        dom.textContent = hint;
        if (disable) {
            button.style.display = 'none';
        } else {
            button.style.display = '';
        }
    }

    // 未知处理
    function unknow(hint) {
        let dom = document.querySelector('#checkHint');
        let button = document.querySelector('.btn-area .el-button--primary');
        dom.classList.remove('allow');
        dom.classList.remove('deny');
        dom.classList.add('unknow');
        dom.textContent = hint;
        button.style.display = '';
    }

    // AI通过
    function aiAllow() {
        let dom = document.querySelector('#aiStatus');
        dom.classList.add('ai-allow');
        dom.classList.remove('ai-deny');
        dom.classList.remove('ai-unknow');
    }

    // AI未通过
    function aiDeny() {
        let dom = document.querySelector('#aiStatus');
        dom.classList.remove('ai-allow');
        dom.classList.add('ai-deny');
        dom.classList.remove('ai-unknow');
    }

    // AI未知
    function aiUnknow() {
        let dom = document.querySelector('#aiStatus');
        dom.classList.remove('ai-allow');
        dom.classList.remove('ai-deny');
        dom.classList.add('ai-unknow');
    }

    // 通过属性访问器获取属性值
    function getPropertyByString(obj, propertyString) {
        let properties = propertyString.split('.'); // 将字符串按 '.' 分割成属性名数组
        let value = obj;
        for (let i = 0; i < properties.length; i++) {
            value = value[properties[i]]; // 通过属性访问器获取属性值
        }
        return value;
    }

    // 解析上限规则
    function parseLimits(limitRulesText) {
        let limits = {};
        limitRulesText.split('\n').forEach(function (line) {
            let lines = line.split(',');
            limits[lines[0] + '|' + lines[1]] = Number(lines[2]);
        });
        return limits;
    }

    // 解析特殊规则
    function parseSpecials(specialRulesText) {
        let rules = [];
        let lines = specialRulesText.split('\n')
        for (let i = 0; i < lines.length; i++) {
            try {
                let rule = JSON.parse(lines[i].replaceAll('\\', '\\\\'));
                rules.push(rule);
            } catch (e) {
            }
        }
        return rules;
    }

    // 加载配置
    function loadConfig() {
        schemaName = localStorage.getItem('schemaName') || '';
        let key = "schema_" + schemaName;
        if (localStorage.getItem(key)) {
            let savedData = JSON.parse(localStorage.getItem(key));
            projectId = savedData[0];
            limitRules = parseLimits(savedData[1]);
            specialRules = parseSpecials(savedData[2]);
        }
    }

    // 初始化
    let schemaName = '';
    let projectId = '';
    let limitRules = {};
    let specialRules = [];
    let currentCollection = null;
    let token = localStorage.getItem('ysf-case-pc-token').replaceAll('"', '');

    // 采集表审核页面执行插件功能
    if (window.location.href.includes('caseManage')) {
        loadConfig();
        showHintBox();

        // 在页面加载完成后调用XHR Interceptor
        window.addEventListener('load', XHRInterceptor);
    }
})();